#include "syntax_parser.h"
#include "errors_warnings.h"

#include "main_container.h"
extern MainContainer * CompilerData;

//<trace_part> ~ trace <numeric_mod>  {trace}
//<trace_part>	~	trace <numeric_mod> ( <arguments> )  {trace}
//<trace_part> ~ ? {int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME}
void Parser::Parse_TracePart(SyntaxTreeNode * parent)
{
#ifdef TRACE
   CompilerData->LogTrace->ReportEntry("Parse_TracePart");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
#ifdef TRACE
        CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif

   if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTrace)
   {
#ifdef TRACE
      CompilerData->LogTrace->ReportLine("Recognized terminal symbol \"trace\"");
#endif
         // write type of production in this node
		   parent->Production = Gr_TracePart__trace_NumericMod;

         // trace
      	SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			// increase counter
			CurrentLexicPosition++;

         // process nonterminal symbol <numeric_mod> 
		   SyntaxTreeNode * newNode = new SyntaxTreeNode();
		   parent->Nodes->Add(newNode);
		   Parse_NumericMod(newNode);

			// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{

			 parent->Production = Gr_TracePart__trace_NumericMod_spLPar_Arguments_spRPar;

			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

			// process nonterminal symbol <arguments> 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			Parse_Arguments(newNode2);

					// process terminal symbol ')' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
			{
				SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode3);
				newNode3->LexUnitID=this->CurrentLexicPosition;
				newNode3->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}

		}
   }
   else if
      (
      (currentUnit.type == LUTypeKeyword && ( 
		currentUnit.subtype == KeywordInt ||
		currentUnit.subtype == KeywordFloat ||
		currentUnit.subtype == KeywordBool ||
		currentUnit.subtype == KeywordState ||
		currentUnit.subtype == KeywordTime ||
		currentUnit.subtype == KeywordVoid ||
		currentUnit.subtype == KeywordFacility ||
		currentUnit.subtype == KeywordStorage ||
		currentUnit.subtype == KeywordQueue ||
		currentUnit.subtype == KeywordADTable ||
		currentUnit.subtype == KeywordGroup ||
		currentUnit.subtype == KeywordOutputStream))||
		//NAME
		(currentUnit.type == LUTypeIdentifier ))
   {
         // write type of production in this node
		   parent->Production = Gr_TracePart__epsilon;
   }
   else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_TRACE_PART_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_TracePart");
#endif
}


// <variable_definition> ~ <trace_part> <data_type> <field_names> ;  {int, float, bool, state, time, void,
//Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, trace}
void Parser::Parse_VariableDefinition(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_VariableDefinition");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {int, float, bool, state, time, void,
	//Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, trace}
	if(	//Keyword
		(currentUnit.type == LUTypeKeyword && ( 
		currentUnit.subtype == KeywordInt ||
		currentUnit.subtype == KeywordFloat ||
		currentUnit.subtype == KeywordBool ||
		currentUnit.subtype == KeywordState ||
		currentUnit.subtype == KeywordTime ||
		currentUnit.subtype == KeywordVoid ||
		currentUnit.subtype == KeywordFacility ||
		currentUnit.subtype == KeywordStorage ||
		currentUnit.subtype == KeywordQueue ||
		currentUnit.subtype == KeywordADTable ||
		currentUnit.subtype == KeywordGroup ||
		currentUnit.subtype == KeywordOutputStream||
      currentUnit.subtype == KeywordTrace)) ||
		//NAME
		(currentUnit.type == LUTypeIdentifier ))
	{
		// write type of production in this node
		parent->Production = Gr_VariableDefinition__TracePart_DataType_FieldNames_spSemiCol;

		// process nonterminal symbol <trace_part> 
		SyntaxTreeNode * newNode = new SyntaxTreeNode();
		parent->Nodes->Add(newNode);
		Parse_TracePart(newNode);

		// process nonterminal symbol <data_type> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_DataType(newNode0);

		// process nonterminal symbol <field_names> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_FieldNames(newNode1);

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {;}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_VARIABLE_DEFINITION_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_VariableDefinition");
#endif
}



// <method_call> ~ <name> ( <arguments> ) ;  {NAME}
// <method_call> ~ <variable_value> . NAME ( <arguments> ) ;  {NAME}
void Parser::Parse_MethodCall(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_MethodCall");
#endif
	
	LexicUnit currentUnit;
	LexicUnit nextUnit;

	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// get the next lexic unit to solve the ambiguity
	nextUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition+1);
	
	// if current lexic unit is in the select set of {NAME} and next lexic unit is nonternminal
	// symbol '(', so that ambiguity can be solved
	if(currentUnit.type == LUTypeIdentifier && (nextUnit.type == LUTypeSpecialCharacter && nextUnit.subtype == SpecialCharacterLeftParenthesis))
	{
		// write type of production in this node
		parent->Production =Gr_MethodCall__NAME_spLPar_Arguments_spRPar_spSemiCol;

		// process terminal symbol 'NAME' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <arguments> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Arguments(newNode2);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			newNode4->LexUnitID=this->CurrentLexicPosition;
			newNode4->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	// if current lexic unit is in the select set of {NAME}
	else if(currentUnit.type == LUTypeIdentifier)
	{
		// write type of production in this node
		parent->Production =Gr_MethodCall__VariableValue_spPer_NAME_spLPar_Arguments_spRPar_spSemiCol;

		// process nonterminal symbol <variable_value> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_VariableValue(newNode0);

		// process terminal symbol '.' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PERIOD_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol 'NAME' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if( currentUnit.type == LUTypeIdentifier )
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NAME_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <arguments> 
		SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode4);
		Parse_Arguments(newNode4);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
		{
			SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode5);
			newNode5->LexUnitID=this->CurrentLexicPosition;
			newNode5->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			SyntaxTreeNode * newNode6 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode6);
			newNode6->LexUnitID=this->CurrentLexicPosition;
			newNode6->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}

	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_METHOD_CALL_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_MethodCall");
#endif
}

// <if_statement> ~ if ( <expression> ) <block_statement> <else_part>  {if}
void Parser::Parse_IfStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_IfStatement");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {if}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIf )
	{
		// write type of production in this node
		parent->Production = Gr_IfStatement__if_spLPar_Expression_spRPar_BlockStatement_ElsePart;

		// process terminal symbol 'if' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {(}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Expression(newNode2);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		//if current lexic unit is in the select set of {)}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <block_statement>
		SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode4);
		Parse_BlockStatement(newNode4);

		// process nonterminal symbol <else_part> 
		SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode5);
		Parse_ElsePart(newNode5);

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_IF_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_IfStatement");
#endif
}



// <block_statement>	~	{ <method_body> }
void Parser::Parse_BlockStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_BlockStatement");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {{}
	if( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace )
	{
		// write type of production in this node
		parent->Production = Gr_BlockStatement__spLCBrac_MethodBody_spRCBrac;

		// process terminal symbol '{' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <method_body> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_MethodBody(newNode1);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {}}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}

	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_BlockStatement");
#endif
}


// <else_part> ~ else <block_statement>  {else}
// <else_part> ~ ? {trace, if, while, for, do, switch, break, continue, goto, start, stop, derivation, int, float, bool,
//			state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, },  return}
void Parser::Parse_ElsePart(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ElsePart");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {else}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordElse	)
	{
		// write type of production in this node
		parent->Production = Gr_ElsePart__else_BlockStatement;

		// process terminal symbol 'else' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <block_statement>
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_BlockStatement(newNode1);

	}
	//if current lexic unit is in the select set of {if, while, for, do, switch, break,
	//continue, goto, start, stop, derivation, int, float, bool, state, time, void, 
	//Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, }, case, default, trace, return}
	else if(
		//Keywords
		(currentUnit.type == LUTypeKeyword && (
		currentUnit.subtype == KeywordIf ||
		currentUnit.subtype == KeywordWhile ||
		currentUnit.subtype == KeywordFor ||
		currentUnit.subtype == KeywordDo ||
		currentUnit.subtype == KeywordSwitch ||
		currentUnit.subtype == KeywordBreak ||
		currentUnit.subtype == KeywordContinue ||
		currentUnit.subtype == KeywordGoto ||
		currentUnit.subtype == KeywordStart ||
		currentUnit.subtype == KeywordStop ||
		currentUnit.subtype == KeywordDerivation ||
		currentUnit.subtype == KeywordInt ||
		currentUnit.subtype == KeywordFloat ||
		currentUnit.subtype == KeywordBool ||
		currentUnit.subtype == KeywordState ||
		currentUnit.subtype == KeywordTime ||
		currentUnit.subtype == KeywordVoid ||
		currentUnit.subtype == KeywordFacility ||
		currentUnit.subtype == KeywordStorage ||
		currentUnit.subtype == KeywordQueue ||
		currentUnit.subtype == KeywordADTable ||
		currentUnit.subtype == KeywordGroup ||
		currentUnit.subtype == KeywordOutputStream ||
      currentUnit.subtype == KeywordTrace ||
	  currentUnit.subtype == KeywordReturn))||
		//}
		(currentUnit.type == LUTypeSpecialCharacter &&
		(currentUnit.subtype == SpecialCharacterRightCurlyBrace||currentUnit.subtype == SpecialCharacterLeftCurlyBrace)) ||
		//NAME
		(currentUnit.type == LUTypeIdentifier) 
		)
	{
		// write type of production in this node
		parent->Production = Gr_ElsePart__epsilon;

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_ELSE_PART_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ElsePart");
#endif
}

// <switch_case_statement> ~ switch ( <expression> ) { <switch_case_cases> <switch_case_default> }  {switch}
void Parser::Parse_SwitchCaseStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SwitchCaseStatement");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {switch}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSwitch )
	{
		// write type of production in this node
		parent->Production = Gr_SwitchCaseStatement__switch_spLPar_Expression_spRPar_spLCBrac_SwitchCaseCases_SwitchCaseDefault_spRCBrac;

		// process terminal symbol 'switch' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {(}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Expression(newNode2);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {)}
		if ( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis )
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {{}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
		{
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			newNode4->LexUnitID=this->CurrentLexicPosition;
			newNode4->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <switch_case_cases> 
		SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode5);
		Parse_SwitchCaseCases(newNode5);

		// process nonterminal symbol <switch_case_default> 
		SyntaxTreeNode * newNode6 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode6);
		Parse_SwitchCaseDefault(newNode6);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {}}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace )
		{
			SyntaxTreeNode * newNode7 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode7);
			newNode7->LexUnitID=this->CurrentLexicPosition;
			newNode7->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}

	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SWITCH_CASE_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SwitchCaseStatement");
#endif
}

// <switch_case_cases> ~ <switch_case_case> <switch_case_cases>  {case}
// <switch_case_cases> ~ ? {default, }}
void Parser::Parse_SwitchCaseCases(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SwitchCaseCases");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	do{
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {case}
		if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordCase	)
		{
			// write type of production in this node
			parent->Production = Gr_SwitchCaseCases__SwitchCaseCase_SwitchCaseCases;

			// process nonterminal symbol <switch_case_case> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_SwitchCaseCase(newNode0);
		}

		//if current lexic unit is in the select set of {default, }}
		else if(
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDefault) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace))
		{
			// write type of production in this node
			parent->Production = Gr_SwitchCaseCases__SwitchCaseCase_SwitchCaseCases;
			break;
		}

		else
		{
			// ERROR has been found
			// REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SWITCH_CASE_CASES_BEGINING);
			// This is recovoring from error
			this->CurrentLexicPosition++;
			break;
		}

	}while (1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SwitchCaseCases");
#endif
}

// <switch_case_case> ~ case <expression> : <block_statement>  {case}
void Parser::Parse_SwitchCaseCase(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SwitchCaseCase");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {case}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordCase	)
	{
		// write type of production in this node
		parent->Production = Gr_SwitchCaseCase__case_Expression_spColon_BlockStatement;

		// process terminal symbol 'case' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <expression> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Expression(newNode2);

		// process terminal symbol ':' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {:}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterColon)
		{
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			newNode4->LexUnitID=this->CurrentLexicPosition;
			newNode4->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_COLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <block_statement> 
		SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode5);
		Parse_BlockStatement(newNode5);

	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SWITCH_CASE_CASE_BEGINING);
		// This is recovoring from error
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SwitchCaseCase");
#endif
}


// <switch_case_block> ~ <method_statement>  {trace, if, while, for, do, switch, break, continue, goto, start, stop,
//			derivation, int, float, bool, state, time, void, Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, return}
// <switch_case_block> ~ ? {case, default, }}
// <switch_case_block> ~ { <method_body> }  {{}
/*
void Parser::Parse_SwitchCaseBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SwitchCaseBlock");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {trace, if, while, for, do, switch, break,
	//continue, goto, start, stop, derivation, int, float, bool, state, time, void, 
	//Facility, Storage, Queue, ADTable, Group, OutputStream, NAME, return}
	if(	//Keywords
		(currentUnit.type == LUTypeKeyword && (
		currentUnit.subtype == KeywordIf ||
		currentUnit.subtype == KeywordWhile ||
		currentUnit.subtype == KeywordFor ||
		currentUnit.subtype == KeywordDo ||
		currentUnit.subtype == KeywordSwitch ||
		currentUnit.subtype == KeywordBreak ||
		currentUnit.subtype == KeywordContinue ||
		currentUnit.subtype == KeywordGoto ||
		currentUnit.subtype == KeywordStart ||
		currentUnit.subtype == KeywordStop ||
		currentUnit.subtype == KeywordDerivation ||
		currentUnit.subtype == KeywordInt ||
		currentUnit.subtype == KeywordFloat ||
		currentUnit.subtype == KeywordBool ||
		currentUnit.subtype == KeywordState ||
		currentUnit.subtype == KeywordTime ||
		currentUnit.subtype == KeywordVoid ||
		currentUnit.subtype == KeywordFacility ||
		currentUnit.subtype == KeywordStorage ||
		currentUnit.subtype == KeywordQueue ||
		currentUnit.subtype == KeywordADTable ||
		currentUnit.subtype == KeywordGroup ||
		currentUnit.subtype == KeywordReturn ||
      currentUnit.subtype == KeywordTrace ||
		currentUnit.subtype == KeywordOutputStream )) ||
		//NAME
		(currentUnit.type == LUTypeIdentifier)
		)
	{
		// write type of production in this node
		parent->Production = Gr_SwitchCaseBlock__MethodStatement;

		// process nonterminal symbol <method_statement> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_MethodStatement(newNode0);

	}

	//if current lexic unit is in the select set of {case, default, }}
	else if(
		//Keywords
		(currentUnit.type == LUTypeKeyword && (
		currentUnit.subtype == KeywordCase ||
		currentUnit.subtype == KeywordDefault )) ||
		//}
		(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)


		)
	{
		// write type of production in this node
		parent->Production = Gr_SwitchCaseBlock__epsilon;

	}

	//if current lexic unit is in the select set of {{}
	else if( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace )
	{
		// write type of production in this node
		parent->Production = Gr_SwitchCaseBlock__spLCBrac_MethodBody_spRCBrac;

		// process terminal symbol '{' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <method_body> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_MethodBody(newNode1);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {}}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SWITCH_CASE_BLOCK_BEGINING);
		// This is recovoring from error
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SwitchCaseBlock");
#endif
}
*/

// <switch_case_default> ~ default : <block_statement> {default}
// <switch_case_default> ~ ? {}}
void Parser::Parse_SwitchCaseDefault(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SwitchCaseDefault");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	//if current lexic unit is in the select set of {default}
	if(	currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDefault)
	{
		// write type of production in this node
		parent->Production = Gr_SwitchCaseDefault__default_spColon_BlockStatement;

		// process terminal symbol 'default' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol ':' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		//if current lexic unit is in the select set of {:}
		if (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterColon)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_COLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <block_statement> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_BlockStatement(newNode2);

	}

	//if current lexic unit is in the select set of {}}
	else if( currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace )
	{
		// write type of production in this node
		parent->Production = Gr_SwitchCaseDefault__epsilon;

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SWITCH_CASE_DEFAULT_BEGINING);
		// This is recovoring from error
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SwitchCaseDefault");
#endif
}




